package com.ruoyi.scale.model;

import com.ruoyi.common.utils.json.JsonUtils;
import lombok.Getter;
import lombok.Setter;

import java.util.ArrayList;
import java.util.List;

@Getter
@Setter
public class GrowthOutput extends GrowthInput{
    private String weightSd;
    private String weightSdResult; //结论
    private String weightSdFive;
    private String weightPer;
    private String weightPerFive;

    private String heightSd;
    private String heightSdResult;
    private String heightSdFive;
    private String heightPer;
    private String heightPerFive;


    private String heightWeightSd;
    private String heightWeightSdResult;
    private String heightWeightSdFive;

//    private String bodyLengthPer;
//    private String bodyLengthPerFive;

    private String headCircumferenceSd;
    private String headCircumferenceSdResult;
    private String headCircumferenceSdFive;
    private String headCircumferencePer;
    private String headCircumferencePerFive;

//    private String chestCircumferenceSd;
//    private String chestCircumferenceSdResult;
//    private String chestCircumferenceFive;
//    private String chestCircumferencePer;

    private Double bmi;
    private String bmiSd;
    private String bmiSdResult;
    private String bmiSdFive;
    private String bmiPer;
    private String bmiPerFive;

    private List<Double> heightCategories = new ArrayList<>();
    private List<Double> heightPoints = new ArrayList<>();
    private Double[][] heightLineList;

    private List<Double> weightCategories = new ArrayList<>();
    private List<Double> weightPoints = new ArrayList<>();
    private Double[][] weightLineList;

    private List<Double> bmiCategories = new ArrayList<>();
    private List<Double> bmiPoints = new ArrayList<>();
    private Double[][] bmiLineList;

    private List<Double> bodyLengthCategories = new ArrayList<>();
    private List<Double> bodyLengthPoints = new ArrayList<>();
    private Double[][] bodyLengthLineList;

    /**
     * 一般的匹配方法
     * @param val
     * @param growthOutput
     * @return   sd  five  per
     */

    public String[] matchP3_P25_P75_P97(Double val, GrowthNormData growthOutput){
        String sdStr = "-";
        String fiveStr  = "-";
        String perStr = "-";
        if(val == null || growthOutput == null){
            return new String[]{sdStr,fiveStr,perStr};
        }
        if(val <= growthOutput.getP3()){
            sdStr = "-2SD";
            fiveStr = "下";
            perStr = "<P3";
        }else if(val <= growthOutput.getP25()){
            sdStr = "-(1SD~2SD)";
            fiveStr = "中下";
            perStr = "P3~P25";
        }else if(val <= growthOutput.getP75()){
            sdStr = "±1SD";
            fiveStr = "中";
            perStr = "P25~P75";
        }else if(val <= growthOutput.getP97()){
            sdStr = "+(1SD~2SD)";
            fiveStr = "中上";
            perStr = "P75~P97";
        }else {
            if(val != null) {
                sdStr = "+2SD";
                fiveStr = "上";
                perStr = ">P97";
            }
        }
        return new String[]{sdStr,fiveStr,perStr};
    }

    private Double[][] buildPointAndPoint(GrowthNormData growthNormData, List<Double> categories , List<GrowthNormData> normList){
        int categoriesSize = 23;
        int halfCategoriesSize = categoriesSize / 2;
        Double[] p3 = new Double[categoriesSize];
        Double[] p25 = new Double[categoriesSize];
        Double[] p50 = new Double[categoriesSize];
        Double[] p75 = new Double[categoriesSize];
        Double[] p97 = new Double[categoriesSize];

        int matchGrowthNormIndex = growthNormData != null ? normList.indexOf(growthNormData) : categoriesSize;
        int foreachStart = 0;
        int foreachEnd = normList.size();
        //左边数量够的
        if(matchGrowthNormIndex >= halfCategoriesSize){
            foreachStart = matchGrowthNormIndex - halfCategoriesSize;
            foreachEnd = normList.size() > matchGrowthNormIndex ? (matchGrowthNormIndex + halfCategoriesSize) : normList.size();
            if(foreachEnd > normList.size() -1){
                //如果右边数量不够 则左边向左移动
                foreachStart = foreachStart - (foreachEnd - normList.size() + 1);
                 foreachEnd = normList.size() -1;
            }

        } else {
            foreachStart = 0;
            //前面不足的 + 后面应该有的
            int endTemp = matchGrowthNormIndex + (halfCategoriesSize - matchGrowthNormIndex) + halfCategoriesSize;
            foreachEnd = endTemp >= normList.size() ? normList.size() - 1 : endTemp;
        }


        for (int i = foreachStart; i <= foreachEnd; i++) {
            GrowthNormData tmp = normList.get(i);
            categories.add(tmp.getKeyVal());
            int pos = i - foreachStart;
            p3[pos] = tmp.getP3();
            p25[pos] = tmp.getP25();
            p50[pos] = tmp.getP50();
            p75[pos] = tmp.getP75();
            p97[pos] = tmp.getP97();
        }
        return new Double[][]{p3, p25, p50, p75, p97};
    }

    public static void main(String[] args) {

        List<GrowthNormData> list = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            GrowthNormData growthNormData = new GrowthNormData();
            growthNormData.setKeyVal((double) i);
            growthNormData.setP3((double) i);
            growthNormData.setP25((double) i);
            growthNormData.setP50((double) i);
            growthNormData.setP75((double) i);
            growthNormData.setP97((double) i);
            list.add(growthNormData);
        }

        List<Double> categories = new ArrayList<>();

        GrowthOutput growthOutput = new GrowthOutput();
        for (int i = 0; i < 100; i++) {
            try {
                Double[][] doubles = growthOutput.buildPointAndPoint(list.get(i), categories, list);
                System.out.println(i + "  " + JsonUtils.serialize(doubles[0]));
            }catch (Exception e){
                System.out.println("errr:" + i);
                e.printStackTrace();
            }
        }




    }

    public void assemblerWeight(double monthAge, Double val,
                                GrowthNormData growthSdNormData,
                                List<GrowthNormData> normSdDataList,
                                GrowthNormData growthNormData,
                                List<GrowthNormData> growthPerNormList){

        String[] sdRs = matchP3_P25_P75_P97(val, growthSdNormData);
        this.setWeightSd(sdRs[0]);
        this.setWeightSdFive(sdRs[1]);
        if(growthSdNormData != null){
            String rs = null;
            if(val < growthSdNormData.getP10()){
                rs = "重度低体重";
            } else if ( val < growthSdNormData.getP25()){
                rs = "低体重";
            }
            this.setWeightSdResult(rs);
        }

        String[] perRs = matchP3_P25_P75_P97(val, growthNormData);
        this.setWeightPer(perRs[2]);
        this.setWeightPerFive(perRs[1]);

        //5根标准线
        this.weightLineList = this.buildPointAndPoint(growthSdNormData,weightCategories, normSdDataList);
        //历史记录 TODO

        for (Double category : weightCategories) {
            if (category >= monthAge) {
                this.weightPoints.add(val);
                break;
            }else {
                this.weightPoints.add(null);
            }
        }

    }

    public void assemblerHeight(double monthAge, Double val,
                                GrowthNormData growthSdNormData,
                                List<GrowthNormData> normSdDataList,
                                GrowthNormData growthNormData,
                                List<GrowthNormData> growthPerNormList
                               ){
        String[] sdRs = matchP3_P25_P75_P97(val, growthSdNormData);
        this.setHeightSd(sdRs[0]);
        this.setHeightSdFive(sdRs[1]);
        if(growthSdNormData != null){
            String rs = null;
            if(val < growthSdNormData.getP10()){
                rs = "重度生长迟缓";
            } else if ( val < growthSdNormData.getP25()){
                rs = "生长迟缓";
            }
            this.setHeightSdResult(rs);
        }

        String[] perRs = matchP3_P25_P75_P97(val, growthNormData);
        this.setHeightPer(perRs[2]);
        this.setHeightPerFive(perRs[1]);

        //5根标准线
        this.heightLineList = this.buildPointAndPoint(growthSdNormData,heightCategories, normSdDataList);
//        //历史记录 TODO
        for (Double category : heightCategories) {
            if (category >= monthAge) {
                this.heightPoints.add(val);
                break;
            }else {
                this.heightPoints.add(null);
            }
        }
    }
    public void assemblerHeightWeight(double monthAge, Double val,
                                      GrowthNormData growthSdNormData,
                                      List<GrowthNormData> normSdDataList,
                                      GrowthNormData growthNormData,
                                      List<GrowthNormData> growthPerNormList
                                    ){

        String[] sdRs = matchP3_P25_P75_P97(val, growthSdNormData);
        this.setHeightWeightSd(sdRs[0]);//heightWeight
        this.setHeightWeightSdFive(sdRs[1]);
        if(growthSdNormData != null){
            String rs = null;
            if (val >= growthSdNormData.getP97()) {
                rs = "重度肥胖";
            } else if(val >= growthSdNormData.getP90()){
                rs = "肥胖";
            } else if(val >= growthSdNormData.getP75()){
                rs = "超重";
            }  else if( val < growthSdNormData.getP3()){
                rs = "重度消瘦";
            } else if(val < growthSdNormData.getP10()){
                rs = "消瘦";
            }
            this.setHeightWeightSdResult(rs);
        }

        //5根标准线
      /*  this.bodyLengthLineList = this.buildPointAndPoint(growthNormData,bodyLengthCategories, normList);
//        //历史记录 TODO
        for (Double category : bodyLengthCategories) {
            if (category >= val) {
                this.bodyLengthPoints.add(val);
                break;
            }else {
                this.bodyLengthPoints.add(null);
            }
        }*/

    }

    public void assemblerBmi(double monthAge, Double val,
                             GrowthNormData growthSdNormData,
                             List<GrowthNormData> normSdDataList,
                             GrowthNormData growthNormData,
                             List<GrowthNormData> growthPerNormList
                             ){
        this.setBmi(val);
        String[] rsSd = matchP3_P25_P75_P97(val, growthSdNormData);
        this.setBmiSd(rsSd[0]);
        this.setBmiSdFive(rsSd[1]);
        if(growthSdNormData != null){
            if(growthSdNormData != null){
                String rs = null;
                if (val >= growthSdNormData.getP97()) {
                    rs = "重度肥胖";
                } else if(val >= growthSdNormData.getP90()){
                    rs = "肥胖";
                } else if(val >= growthSdNormData.getP75()){
                    rs = "超重";
                }  else if( val < growthSdNormData.getP3()){
                    rs = "重度消瘦";
                } else if(val < growthSdNormData.getP10()){
                    rs = "消瘦";
                }
                this.setBmiSdResult(rs);
            }
        }
        //百分位
        String[] perRs = matchP3_P25_P75_P97(val, growthNormData);
        this.setBmiPer(perRs[2]);
        this.setBmiPerFive(perRs[1]);

        //5根标准线
        this.bmiLineList = this.buildPointAndPoint(growthSdNormData,bmiCategories, normSdDataList);
//        //历史记录 TODO
        for (Double category : bmiCategories) {
            if (category >= monthAge) {
                this.bmiPoints.add(val);
                break;
            }else {
                this.bmiPoints.add(null);
            }
        }
    }

    public void assemblerTw(double monthAge, Double val,
                            GrowthNormData growthSdNormData,
                            GrowthNormData growthNormData
                           ){

        String[] sdRs = matchP3_P25_P75_P97(val, growthSdNormData);
        this.setHeadCircumferenceSd(sdRs[0]);
        this.setHeadCircumferenceSdFive(sdRs[1]);
        if(growthSdNormData != null){
            String rs = null;
            if(val < growthSdNormData.getP10()){
                rs = "重度低体重";
            } else if ( val < growthSdNormData.getP25()){
                rs = "低体重";
            }
            this.setWeightSdResult(rs);
        }

        String[] perRs = matchP3_P25_P75_P97(val, growthNormData);
        this.setHeadCircumferencePer(perRs[2]);
        this.setHeadCircumferencePerFive(perRs[1]);
    }

    public void assemblerXw(double monthAge, Double val, GrowthNormData growthNormData){
//        String[] rs = matchP3_P25_P75_P97(val, growthNormData);
//        this.setChestCircumferenceSd(rs[0]);
//        this.setChestCircumferenceFive(rs[1]);
//        this.setChestCircumferencePer(rs[2]);
    }


}
